// **************************************************************
// COPYRIGHT(c)2021, Xidian University
// All rights reserved.
//
// IP LIB INDEX :  
// IP Name      :      
// File name    :  
// Module name  : axis_clock_converter_nb64_256.v 
// Full name    :  
// Time         : 2021 
// Author       : Haoxiaofei 
// Email        : 1531804419@qq.com
// Data         : 
// Version      : V 1.0 
// 
// Abstract     :
// Called by    :  
// 
// Modification history
// -----------------------------------------------------------------
// \u4fee\u6539\u4f7f\u5176\u5bf9\u5e94AXI_stream\u683c\u5f0f
// 
//
// *****************************************************************
// TIMESCALE
// ******************* 
`timescale 1ns/1ps 

module axis_clock_converter_nb64_256#(parameter  WIZE_I = 64 , WIZE_O = 256 , MULTI = 4 , MULTI_ADDR_W = 2 , KEEP_W_I = 8 , KEEP_W_O = 32 ,TUSER_W = 90)
(
    input wire [ 9 :0]ram_2p_cfg_register,
    input  wire        m_axis_clk        ,
    input  wire        m_axis_rst_n      ,
//64bit  in
    input  wire        m_axis_rtvalid_in ,
    output wire        m_axis_rtready_out,
    input  wire[63 :0] m_axis_rtdata_in  ,  
    input  wire[7  :0] m_axis_rtkeep_in  ,
    input  wire        m_axis_rtlast_in  , 
    // input  wire[89 :0] m_axis_rtuser_in  ,

//256bit  out 
    output reg         m_axis_rtvalid_out ,
    input  wire        m_axis_rtready_in  ,
    output reg[255:0]  m_axis_rtdata_out  ,
    output reg[31 :0]  m_axis_rtkeep_out  ,
    output reg         m_axis_rtlast_out  
    // output reg[89 :0]  m_axis_rtuser_out 
);
//-------------------------------------
//\u7b2c\u4e8c\u90e8\u5206,\u4f4d\u5bbd\u8f6c\u6362
//-------------------------------------
//parameter MIN_GAP = 6 ; //10G\u6700\u77ed\u5e27\u95f4\u9694

//REGS
//in_dl1
reg        m_axis_rtvalid_in_dl1 ;
reg        m_axis_rtready_out_dl1 ;
reg[63 :0] m_axis_rtdata_in_dl1  ;
reg[7  :0] m_axis_rtkeep_in_dl1  ;
reg        m_axis_rtlast_in_dl1  ;
// reg[89 :0] m_axis_rtuser_in_dl1  ;

reg        m_axis_rtlast_in_dl2  ;                 


//fifo in
reg [74:0]  fifo_data_in      ; //|ready| |valid| |last| |32keep| |data|//98bit ready\u6682\u65f6\u7f6e\u7a7a
reg         fifo_data_we      ;
reg      fifo_data_rd_temp ;
reg      fifo_data_rd_dl1  ;
reg      fifo_data_rd_dl2  ;

//WIRE
//fifo
wire       fifo_data_full  ;
wire       fifo_data_empty ;
wire        fifo_data_rd    ;
//(--XXXX--)//
wire [(64+3+8)*4-1:0] fifo_data_out   ;
reg m_axis_rtvalid_in_dl2;
wire frame_end;


reg [6:0] pkt_num ; //fifo\u91cc\u9762\u7684\u5e27\u6570

//-------------------------------------
//MAIN
//-------------------------------------
assign m_axis_rtready_out = ~fifo_data_full;
// assign m_axis_rtready_in  = ~fifo_data_empty;

//\u8f93\u5165\u4fe1\u53f7\u6253\u62cd
always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
    if (m_axis_rst_n==1'b0) begin
        m_axis_rtvalid_in_dl1  <= 'b0 ;
        m_axis_rtready_out_dl1  <= 'b0 ;
        m_axis_rtdata_in_dl1   <= 'b0 ;
        m_axis_rtkeep_in_dl1   <= 'b0 ;
        m_axis_rtlast_in_dl1   <= 'b0 ;
        m_axis_rtlast_in_dl2   <= 'b0 ;
        m_axis_rtvalid_in_dl2   <= 'b0 ;
    end
    else begin
        m_axis_rtvalid_in_dl1  <= m_axis_rtvalid_in     ; 
        m_axis_rtready_out_dl1  <= m_axis_rtready_out     ;
        m_axis_rtdata_in_dl1   <= m_axis_rtdata_in      ;
        m_axis_rtkeep_in_dl1   <= m_axis_rtkeep_in      ;
        m_axis_rtlast_in_dl1   <= m_axis_rtlast_in      ;
        m_axis_rtvalid_in_dl2  <= m_axis_rtvalid_in_dl1 ; 
        m_axis_rtlast_in_dl2   <= m_axis_rtlast_in_dl1  ;
    end
end
//-------------------------------------
//FIFO_IN
//-------------------------------------
//fifo\u5199\u6570\u636e 
//|ready| |valid| |last| |keep| |data|//75bit fifo_data_in\u4e2dready\u6682\u65f6\u7f6e\u7a7a
always @(posedge m_axis_clk ) begin
    if (m_axis_rst_n == 1'b0)
        fifo_data_in <= 'b0 ;
    else if (m_axis_rtvalid_in_dl1 /* && m_axis_rtready_out_dl1 */ )//\u540c\u65f6\u62c9\u9ad8\u624d\u80fd\u4ea7\u751f\u5199\u4f7f\u80fd\uff0c\u6b64\u5904\u6216\u8bb8\u4e0d\u7528ready\u5224\u5b9a
        fifo_data_in <= {1'b0,m_axis_rtvalid_in_dl1,m_axis_rtlast_in_dl1,m_axis_rtkeep_in_dl1,m_axis_rtdata_in_dl1} ;
    else
        fifo_data_in <= 'b0 ;
end

//fifo\u5199\u4f7f\u80fd valid&ready\u540c\u65f6\u7f6e\u4f4d\u4f20\u8f93\u5f00\u59cb\u5426\u5219\u4e0d\u80fd\u5199\u5165\u6570\u636e
always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
    if (m_axis_rst_n == 1'b0) 
        fifo_data_we <= 1'b0 ;
    else if (m_axis_rtvalid_in_dl1==1'b1 /*&& m_axis_rtready_out_dl1*/  /*&&full==1'b0*/) begin //\u7406\u8bba\u4e0a\u8981\u8981\u5224\u65adfull,\u8fd9\u91cc\u4e0d\u5224\u65ad
        fifo_data_we <= 1'b1 ;    
    end
    else begin
        fifo_data_we <= 1'b0 ;    
    end
end


//-------------------------------------
//FIFO_OUT
//-------------------------------------
assign frame_end = m_axis_rtlast_in_dl2 & m_axis_rtvalid_in_dl2;

always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
 if (m_axis_rst_n == 1'b0) begin
     pkt_num <= 7'd0 ;
 end
 else if ( m_axis_rtlast_out == 1'b1 && frame_end== 1'b1 ) begin
     pkt_num <= pkt_num ;
 end
 else if ( m_axis_rtlast_out == 1'b1 ) begin
     pkt_num <= pkt_num - 7'd1 ;
 end
 else if ( frame_end == 1'b1 ) begin
     pkt_num <= pkt_num + 7'd1 ;
 end
 else begin
     pkt_num <= pkt_num ;
 end
end

//fifo_data_rd_temp
always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
 if (m_axis_rst_n == 1'b0) begin
     fifo_data_rd_temp <= 1'b0 ; 
 end
 else if ( fifo_data_rd_temp == 1'b1 && fifo_data_rd == 1'b0 )
     fifo_data_rd_temp <= 1'b0 ; 
 else if ( fifo_data_empty == 1'b0 && pkt_num > 7'd0 && m_axis_rtready_in) begin
     fifo_data_rd_temp <= 1'b1 ;
 end
 else begin
     fifo_data_rd_temp <= 1'b0 ; 
 end
end

//
assign fifo_data_rd = fifo_data_rd_temp & ( ! m_axis_rtlast_out ) ;

//fifo_data_rd_dl1
always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
 if (m_axis_rst_n == 1'b0) begin
     fifo_data_rd_dl1 <= 1'b0 ;
     fifo_data_rd_dl2 <= 1'b0 ;
 end
 else begin
     fifo_data_rd_dl1 <= fifo_data_rd ;
     fifo_data_rd_dl2 <= fifo_data_rd_dl1 ;
 end
end
//-------------------------------------
//OUT
//-------------------------------------
//m_axis_rtvalid_out
always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
    if (m_axis_rst_n == 1'b0) 
        m_axis_rtvalid_out <= 1'b0   ;
    else if ( fifo_data_rd_dl2 == 1'b1 ) 
        m_axis_rtvalid_out <= 1'b1  ;
    else 
        m_axis_rtvalid_out <= 1'b0   ;
end

//m_axis_rtkeep_out 
//always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
//    if (m_axis_rst_n == 1'b0) 
//        m_axis_rtkeep_out  <= 32'b0    ;
//    else if ( fifo_data_rd_dl2 == 1'b1 ) begin
//       casex( {fifo_data_out[(64+3+8)*1-2] , fifo_data_out[(64+3+8)*2-2], fifo_data_out[(64+3+8)*3-2], fifo_data_out[(64+3+8)*4-2] } )//\u6700\u9ad8\u4f4d\u7f6e0,\u4e0b\u4e00\u4f4d\u662fvalid
//            4'b1xxx : m_axis_rtkeep_out  <= {fifo_data_out[(64+3+8)*0+64+8-1:64+(64+3+8)*0],8'hff,8'hff,8'hff};
//            4'b01xx : m_axis_rtkeep_out  <= {8'h00,fifo_data_out[(64+3+8)*1+64+8-1:64+(64+3+8)*1],8'hff,8'hff};
//            4'b001x : m_axis_rtkeep_out  <= {8'h00,8'h00,fifo_data_out[(64+3+8)*2+64+8-1:64+(64+3+8)*2],8'hff};
//            4'b0001 : m_axis_rtkeep_out  <= {8'h00,8'h00,8'h00,fifo_data_out[(64+3+8)*3+64+8-1:64+(64+3+8)*3]};
//            default :begin
//                      m_axis_rtkeep_out  <= 32'b0    ;
//            end
//        endcase
//   end
//    else 
//        m_axis_rtkeep_out  <= 32'b0   ;    
//end
always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
    if (m_axis_rst_n == 1'b0) 
        m_axis_rtkeep_out  <= 32'b0    ;
    else if ( fifo_data_rd_dl2 == 1'b1 ) begin
        if (fifo_data_out[(64+3+8)*1-2]) begin
            m_axis_rtkeep_out  <= {fifo_data_out[(64+3+8)*0+64+8-1:64+(64+3+8)*0],8'hff,8'hff,8'hff};
        end
        else if(fifo_data_out[(64+3+8)*2-2]) begin
            m_axis_rtkeep_out  <= {8'h00,fifo_data_out[(64+3+8)*1+64+8-1:64+(64+3+8)*1],8'hff,8'hff};
        end
        else if(fifo_data_out[(64+3+8)*3-2]) begin
            m_axis_rtkeep_out  <= {8'h00,8'h00,fifo_data_out[(64+3+8)*2+64+8-1:64+(64+3+8)*2],8'hff};
        end
        else if(fifo_data_out[(64+3+8)*4-2]) begin
            m_axis_rtkeep_out  <= {8'h00,8'h00,8'h00,fifo_data_out[(64+3+8)*3+64+8-1:64+(64+3+8)*3]};
        end
        else begin
            m_axis_rtkeep_out  <= 32'b0   ; 
        end
    end
    else 
        m_axis_rtkeep_out  <= 32'b0   ;    
end

//m_axis_rtlast_out   {m_axis_rtlast0 | m_axis_rtlast1 | m_axis_rtlast2 | m_axis_rtlast3}\u53d6\u6700\u540e\u4e00\u4e2alast
always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
    if (m_axis_rst_n == 1'b0) 
        m_axis_rtlast_out   <= 1'b0   ;
    else if ( fifo_data_rd_dl2 == 1'b1 )
        m_axis_rtlast_out   <= fifo_data_out[(64+3+8)*1 - 3 ]  |  fifo_data_out[(64+3+8)*2 - 3 ] |  fifo_data_out[(64+3+8)*3 - 3 ] |  fifo_data_out[(64+3+8)*4 - 3 ]  ;
    else
        m_axis_rtlast_out   <= 1'b0   ;
end

//m_axis_rtdata_out
always @(posedge m_axis_clk or negedge m_axis_rst_n) begin
    if (m_axis_rst_n == 1'b0) 
        m_axis_rtdata_out <= 'd0    ;
    else if ( fifo_data_rd_dl2 == 1'b1 )
        m_axis_rtdata_out <= { fifo_data_out[(64+3+8)*0+64-1:(64+3+8)*0] , fifo_data_out[(64+3+8)*1+64-1:0+(64+3+8)*1] ,
                               fifo_data_out[(64+3+8)*2+64-1:(64+3+8)*2] , fifo_data_out[(64+3+8)*3+64-1:0+(64+3+8)*3] } ;
    else
        m_axis_rtdata_out <= 'd0 ;
end

//-------------------------------------
//sub_module
//-------------------------------------
//--XXXX--
axi_width_64_conver_256_data_fifo #(
    .DEPTH                (95               ),
    .ADDR                 (7                ),
    .ALMOST_FULL          (94               ),
    .WIDTH_IN             (64+3+8          ),
    .WIDTH_OUT            ((64+3+8)*4      ),
    .MULTI                (4                ), 
    .MULTI_ADDR           (2                )
    )U_width_64_conver_256_data_fifo(
    .ram_2p_cfg_register(ram_2p_cfg_register),
    .clk                  (m_axis_clk                 ),
    .rst_n                (m_axis_rst_n               ),
    .frame_end            (frame_end                  ), //\u5199\u4e00\u6b21\uff0c\u6240\u4ee5\u53ef\u80fd\u4f1a\u4f7f\u4e24\u4e2a\u5e27\u5408\u5728\u540c\u4e00\u6b21\u6570\u636e\u4e2d\uff0c\u8fd9\u662f\u4e0d\u884c\u7684\uff0c\u5916\u56f4\u5199\u7684\u65f6\u5019\u8865\u96f6,\u4f46\u8865\u96f6\u7684\u6b21\u6570\u4e3a0-MULTI-1\uff0c
                                                         //\u8017\u65f6\u53ef\u80fd\u8f83\u5927\uff0c\u6240\u4ee5\u7528\u8be5\u4fe1\u53f7\u4e00\u6b21\u8865\u591a\u4e2a\u96f6,\u5bf9\u5e94locallink eop
    //w
    .fifo_wr_en           (fifo_data_we               ),
    .fifo_data_in         (fifo_data_in               ),
    .fifo_full_wr         (fifo_data_full             ),
    .almost_full          (                           ),
    //r
    .fifo_rd_en           (fifo_data_rd               ),
    .fifo_data_out        (fifo_data_out              ),
    .fifo_empty_rd        (fifo_data_empty            )
);



endmodule

